import java.util.Random;

import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.plugin.PlugIn;
import ij.process.ByteProcessor;
import ij.process.ImageProcessor;


public class testPlugin implements PlugIn {

	static int W = 400;					// width of the new image
	static int H = 300;					// height of the new image
	
	static double xc = 200;				// x-center of the circle
	static double yc = 150;				// y-center of the circle
	static double rad = 100;			// radius of the circle
	
	static double xySigma = 0.5;		// standard variation of position noise
	static int onCirclePts = 150;		// number of points ON the circle
	static int offCirclePts = 100;		// number of additional random points 
	
	static String imageTitle = "circle-test";

	@Override
	public void run(String arg0) {
		if (!getUserInput()) {
			return;
		}
		
		// create a new grayscale image
		ImageProcessor ip = new ByteProcessor(W, H);
		ip.invertLut();					// to show white background
		
		Random rg = new Random();
		
		// create random points on the circle
		for (int i = 0; i < onCirclePts; i++) {
			double phi = rg.nextDouble() * 2 * Math.PI;	// uniformly distributed angle 0,...,2pi
			double dx = xySigma * rg.nextGaussian();	// position disturbed by Gaussian noise
			double dy = xySigma * rg.nextGaussian();
			int u = (int) Math.round(xc + rad * Math.cos(phi) + dx);
			int v = (int) Math.round(yc + rad * Math.sin(phi) + dy);
			ip.putPixel(u, v, 255);
		}
		
		// create additional random points uniformly distributed in the image
		for (int i = 0; i < offCirclePts; i++) {
			int u = rg.nextInt(W);
			int v = rg.nextInt(H);
			ip.putPixel(u, v, 255);
		}
		
		// display the new image
		(new ImagePlus(imageTitle, ip)).show();
		
	}
	
	boolean getUserInput() {
		GenericDialog gd = new GenericDialog("Create Circle Test Image");
		gd.addNumericField("Image width", W, 0);
		gd.addNumericField("Image height", H, 0);
		gd.addNumericField("Center xc", xc, 2);
		gd.addNumericField("Center yc", yc, 2);
		gd.addNumericField("Radius r", rad, 2);
		gd.addNumericField("Position Noise sigma", xySigma, 2);
		gd.addNumericField("No. of ON-Circle Points", onCirclePts, 0);
		gd.addNumericField("No. of OFF-Circle Points", offCirclePts, 0);
		gd.showDialog();
		if (gd.wasCanceled()) {
			return false;
		}
		W = (int) gd.getNextNumber();
		H = (int) gd.getNextNumber();
		xc = gd.getNextNumber();
		yc = gd.getNextNumber();
		rad = gd.getNextNumber();
		xySigma = gd.getNextNumber();
		onCirclePts = (int) gd.getNextNumber();
		offCirclePts = (int) gd.getNextNumber();
		return true;
	}

}
